package org.monkey.socket.plugin.config;

import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.monkey.socket.plugin.entity.WebSocketProperties;
import org.monkey.socket.plugin.handler.DefaultMsgAcceptFailedHandler;
import org.monkey.socket.plugin.handler.DefaultMsgAcceptHandler;
import org.monkey.socket.plugin.handler.DefaultMsgSendFailedHandler;
import org.monkey.socket.plugin.handler.NioWebSocketHandler;
import org.monkey.socket.plugin.provider.DefaultIMsgConsumer;
import org.monkey.socket.plugin.provider.DefaultIMsgProducer;
import org.monkey.socket.plugin.provider.DefaultMsgChannelManage;
import org.monkey.socket.plugin.provider.DefaultMsgDealAction;
import org.monkey.socket.plugin.provider.MsgAcceptProvider;
import org.monkey.socket.plugin.service.IMsgAcceptFailedHandler;
import org.monkey.socket.plugin.service.IMsgChannelManage;
import org.monkey.socket.plugin.service.IMsgConsumer;
import org.monkey.socket.plugin.service.IMsgDealAction;
import org.monkey.socket.plugin.service.IMsgProducer;
import org.monkey.socket.plugin.service.IMsgPushService;
import org.monkey.socket.plugin.service.IMsgSendFailedHandler;
import org.monkey.socket.plugin.service.impl.DefaultMsgPushService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

/**
 * 默认注入类
 * @author LiTing
 * @date 2022/6/10 19:12
 **/
@Slf4j
@AutoConfiguration
@ConditionalOnProperty(prefix = "websocket", name = "enable", havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties({WebSocketProperties.class})
public class SocketBeanAutoConfig {

  @Autowired
  WebSocketProperties webSocketProperties;

  @ConditionalOnMissingBean(IMsgSendFailedHandler.class)
  @Bean
  public IMsgSendFailedHandler defaultMsgSendFailedHandler() {
    log.info("init default MsgSendFailedHandler... ");
    return new DefaultMsgSendFailedHandler();
  }

  @ConditionalOnMissingBean(IMsgAcceptFailedHandler.class)
  @Bean
  public IMsgAcceptFailedHandler defaultMsgAcceptFailedHandler() {
    log.info("init default MsgAcceptFailedHandler... ");
    return new DefaultMsgAcceptFailedHandler();
  }

  @ConditionalOnMissingBean(MsgAcceptProvider.class)
  @Bean
  public  MsgAcceptProvider msgAcceptProvider(IMsgAcceptFailedHandler iMsgAcceptFailedHandler,IMsgChannelManage msgChannelManage) {
    log.info("init msgAcceptProvider... ");
    DefaultMsgAcceptHandler defaultMsgAcceptHandler = new DefaultMsgAcceptHandler(msgChannelManage);
    MsgAcceptProvider msgAcceptProvider = new MsgAcceptProvider(iMsgAcceptFailedHandler);
    msgAcceptProvider.addAcceptHandler(defaultMsgAcceptHandler);
    return msgAcceptProvider;
  }

  @Bean
  @ConditionalOnClass(DefaultMQProducer.class)
  @ConditionalOnProperty(prefix = "websocket", name = "rocketmq.enable", havingValue = "true", matchIfMissing = false)
  public SocketMqConfig socketMqConfig() {
    return new SocketMqConfig();
  }

  @ConditionalOnMissingBean(IMsgProducer.class)
  @ConditionalOnBean(SocketMqConfig.class)
  @Bean(name = "defaultIMsgProducer")
  public IMsgProducer iMsgProducer(SocketMqConfig socketMqConfig) {
    log.info("init iMsgProducer,this bean is for publish to middleware. ");
    return new DefaultIMsgProducer(socketMqConfig);
  }

  @ConditionalOnBean(SocketMqConfig.class)
  @ConditionalOnMissingBean(IMsgConsumer.class)
  @Bean
  public DefaultIMsgConsumer defaultMsgConsumer(MsgAcceptProvider msgAcceptProvider,
      SocketMqConfig socketMqConfig) {
    log.info("init msg receiver from middleware.the business of msg received you can see MsgAcceptProvider ");
    return new DefaultIMsgConsumer(msgAcceptProvider, socketMqConfig);
  }
  @ConditionalOnMissingBean(IMsgDealAction.class)
  @Bean
  public IMsgDealAction msgDealAction(IMsgProducer iMsgProducer,IMsgSendFailedHandler msgSendFailedHandler){
    log.info("init msg deal action ,this bean is for handler and publish msg ");
    return new DefaultMsgDealAction(iMsgProducer,msgSendFailedHandler);
  }
  @ConditionalOnMissingBean(NioWebSocketHandler.class)
  @Bean
  public NioWebSocketHandler nioWebSocketHandler(IMsgDealAction msgDealAction,IMsgChannelManage msgChannelManage) {
    log.info("init netty handler, this bean just for docked netty ,no other service business,if you want known the  business of msg deal ,you can see DefaultMsgDealAction");
    return new NioWebSocketHandler(msgDealAction,msgChannelManage);
  }

  @ConditionalOnMissingBean(NioWebSocketChannelInitializer.class)
  @Bean
  public NioWebSocketChannelInitializer webSocketChannelInitializer(NioWebSocketHandler webSocketHandler) {
    log.info("init webSocketChannelInitializer... ");
    return new NioWebSocketChannelInitializer(webSocketProperties, webSocketHandler);
  }

  @ConditionalOnMissingBean(NioWebSocketServer.class)
  @Bean
  public NioWebSocketServer nioWebSocketServer(
      NioWebSocketChannelInitializer nioWebSocketChannelInitializer) {
    log.info("init nioWebSocketServer...");
    return new NioWebSocketServer(webSocketProperties, nioWebSocketChannelInitializer);
  }
  @ConditionalOnMissingBean(IMsgPushService.class)
  @Bean
  public IMsgPushService defaultMsgPushService(IMsgDealAction msgDealAction){
    log.info("init IMsgPushService, you can autowired it in your business code to send msg");
    return new DefaultMsgPushService(msgDealAction);
  }

  @ConditionalOnMissingBean(IMsgChannelManage.class)
  @Bean
  IMsgChannelManage defaultMsgChannelManage(){
    log.info("init defaultMsgChannelManage, this bean is for manage netty channel and user login logout business");
    return new DefaultMsgChannelManage(webSocketProperties);
  }
}
